const { $copy, $toClass, $trimAll, $isType } = require('./common')
// 小程序环境变量  默认开发环境
const { host, api, token, tokenKey, beforeFail } = require('./config')

/*
    $request(assParams:String|Object[,data:String|Object])
    网络请求 基于 uni.request api
    参数字典
    assParams -- String|Object   #required  // 请求路径 或  配置参数
    {
        url: String 
        ,header: Object || [undefined,null,""]
        ,join: Boolean 
        ,loading: Object || any
    }
    data -- String | Object   // 请求参数 
    由于配置全局接口路径  
    需要请求其他url路径或其他请求配置请在 assParams 配置参数
    主意 assParams 为 Object时  默认进行浅合并  url默认拼接全局 api路径
    当 assParams 中 join 为 false  会直接替换
    loading 默认为一个对象 传入wx loading api配置参数 ,如果不要loading 可以是设置为 非 Object类型
    url 必须为完整 api assParams 
    考虑异步性能与复杂性 请注意
    尽量忽略  success fail 回调  请按 promise调用
    方法 api 参考 axios


*/

function $request(assParams, data, method = 'GET') {
  const vm = this
  return new Promise((resolve, reject) => {
    //  参数合并
    if (assParams) {
      let defaultOpts = {
        // 接口地址
        url: '',
        // 传送数据
        // data: {},
        header: {
          'content-type': 'application/json',
          // 定义前后台身份标识  默认token标识为
          [tokenKey]: token()
        },
        // 是否进行url参数拼接 默认拼接 false  直接替换
        join: true,
        // 请求方法
        method
        // loading 弹框文字 { title:"loading..." }
        // ,loading: { title:"loading..." }
      }

      if (data) {
        defaultOpts.data = data
      }
      const optsType = $toClass(assParams)
      if (optsType === 'String') {
        defaultOpts.url = host + api + assParams
      } else if (optsType === 'Object') {
        $copy(defaultOpts, assParams)
        if (defaultOpts.join) {
          defaultOpts.url = host + api + assParams.url
        } else {
          defaultOpts.url = assParams.url
        }
      } else {
        throw new TypeError('the params type is must be String or Object')
      }
      const { url, loading } = defaultOpts

      if (url && typeof url == 'string' && $trimAll(url)) {
        const loadingAuto = $isType(loading, 'Object')
        if (loading && loadingAuto) {
          uni.showLoading(loading)
        }
     
        const route = getCurrentPages()
        if (route[1]?.route === 'pages/login/index') return
        uni.request(
          $copy(defaultOpts, {
            success(res) {
              if (loading && loadingAuto) {
                uni.hideLoading()
              }

              /* 根据后台控制器修改 */
              const { statusCode, errMsg, code } = res
              const statusReg = /^[23]0\d$/
              if (statusReg.test(statusCode)) {
                const resData = res.data
                const { code } = resData
                if (code === 'A00004') {
                  uni.reLaunch({
                    url: '/pages/login/index'
                  })
                  return
                }
                let statusCode = 0
                if (statusReg.test(code)) {
                  statusCode = 1
                }
                resData.statusCode = statusCode
                function next() {
                  resolve(resData)
                }
                if (beforeFail && typeof beforeFail === 'function') {
                  const pagesArr = getCurrentPages()
                  const curPage = pagesArr[pagesArr.length - 1]
                  beforeFail(resData, { vm: curPage.$vm }, next)
                } else {
                  resolve(resData)
                }
              } else {
                reject(`errMsg=${errMsg},statusCode=${statusCode}`)
              }
            },
            fail(error) {
              if (loading && loadingAuto) {
                uni.hideLoading()
              }
              reject(error || '请求失败')
            }
          })
        )
      } else {
        throw new Error('missing necessary parameters or type error of url')
      }
    } else {
      throw new ReferenceError('the params must be required')
    }
  })
}

/* 
    $get(path:String|Object,data:String|Object);
    $get 与 $post 基于 $request方法
    参数类型与request相同
    get  请求
    不做请求方式强制绑定    留待可以扩展其他 post  put delect方式 

*/
function $get(path, data) {
  return $request(path, data)
}
function $post(path, data) {
  return $request(path, data, 'POST')
}
function $put(path, data) {
  return $request(path, data, 'PUT')
}
function $delete(path, data) {
  return $request(path, data, 'DELETE')
}

module.exports = {
  $request,
  $get,
  $post,
  $put,
  $delete
}
